/*
 * ByteQueue.cpp
 *
 *  Created on: 22/06/2014
 *      Author: Vitor
 */

#include "ByteQueue.h"

using namespace std;

ByteQueue::ByteQueue(size_t size) {
	buf.resize(size);
}

ByteQueue::ByteQueue(std::vector<char> buffer) :
		buf(buffer) {
}

size_t ByteQueue::size() const {
	return buf.size();
}

void ByteQueue::resize(size_t size) {
	buf.resize(size);
}

void* ByteQueue::ptr() const {
	return buf.size() ? (void*) &buf[0] : nullptr;
}

ByteQueue ByteQueue::append(ByteQueue other) {
	auto this_bytes = get_raw();
	auto other_bytes = other.get_raw();
	this_bytes.insert(this_bytes.end(), other_bytes.begin(), other_bytes.end());
	return ByteQueue(this_bytes);
}

ByteQueue& ByteQueue::push(const void* data, size_t maxlen) {
	buf.insert(buf.end(), (char*) data, ((char*) data) + maxlen);
	return *this;
}

ByteQueue& ByteQueue::push(const string& data, bool with_null_termination) {
	buf.insert(buf.end(), (char*) data.c_str(),
			((char*) data.c_str()) + data.size());
	if (with_null_termination)
		buf.push_back(char(0));
	return *this;
}

size_t ByteQueue::pop(void* data, size_t maxlen) {
	size_t total = maxlen <= buf.size() ? maxlen : buf.size();
	if (!total)
		return 0;
	memcpy(data, (const void*) &buf[0], total);
	buf.erase(buf.begin(), buf.begin() + total);
	return total;
}

string ByteQueue::pop(size_t maxlen) {
	string data(maxlen <= buf.size() ? maxlen : buf.size(), '0');
	if (data.size()) {
		memcpy((void*) data.c_str(), (const void*) &buf[0], data.size());
		buf.erase(buf.begin(), buf.begin() + data.size());
	}
	return data;
}
